package com.iwhalecloud.citybrain.flow.platform.manager.application.utils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.collections4.CollectionUtils;
import org.flowable.form.model.FormField;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author cheng.huaxing
 * @date 2019-04-12
 */
public class FormUtils {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private FormUtils() {
    }

    private static final FormUtils FORM_UTILS;

    static {
        FORM_UTILS = new FormUtils();
    }

    public static FormUtils getInstance() {
        return FORM_UTILS;
    }

    /**
     * 前端表单数据结构转换
     *
     * @param fields
     * @return
     */
    public List<Object> transformToDBForm(List<Object> fields) {
        List<Object> transformFields = new ArrayList<>(fields.size());
        for (Object field : fields) {
            JSONObject formObject = JSON.parseObject(JsonUtils.toJson(field));
            JSONObject params = formObject.getJSONObject("params");
            if (Objects.isNull(params)) {
                params = new JSONObject();
            }
            String code = formObject.getString("code");
            String defaultValue = formObject.getString("defaultValue");
            if (Objects.nonNull(code)) {
                params.put("code", code);
                formObject.remove("code");
                // 修改id等于code，填写表单赋值需要
                formObject.put("id", code);
            }
            if (Objects.nonNull(defaultValue)) {
                params.put("defaultValue", defaultValue);
                formObject.remove("defaultValue");
            }
            if ("boolean".equals(formObject.getString("type"))) {
                JSONArray options = formObject.getJSONArray("options");
                params.put("options", options);
                formObject.remove("options");
            }
            formObject.put("params", params);
            transformFields.add(formObject.toJavaObject(Object.class));
        }
        return transformFields;
    }

    public <T> List<Object> transformToViewForm(List<T> fields) {
        List<Object> transformFields = new ArrayList<>(fields.size());
        for (T field : fields) {
            JSONObject formObject = JSON.parseObject(JsonUtils.toJson(field));
            JSONObject params = formObject.getJSONObject("params");
            if (Objects.isNull(params)) {
                continue;
            }
            String code = params.getString("code");
            String defaultValue = params.getString("defaultValue");
            if (Objects.nonNull(code)) {
                formObject.put("code", code);
                params.remove("code");
            } else {
                formObject.put("code", formObject.getString("id"));
            }
            if (Objects.nonNull(defaultValue)) {
                formObject.put("defaultValue", defaultValue);
                params.remove("defaultValue");
            }
            if ("boolean".equals(formObject.getString("type"))) {
                JSONArray options = params.getJSONArray("options");
                formObject.put("options", options);
                params.remove("options");
            }
            formObject.put("params", params);
            if ("userRadio".equals(formObject.getString("type"))) {
                String value = formObject.getString("value");
                if (Objects.nonNull(value) && value.contains("_")) {
                    String[] userRadio = value.split("_");
                    JSONObject userObject = new JSONObject();
                    userObject.put("label", userRadio[0]);
                    userObject.put("value", userRadio[1]);
                    formObject.put("value", userObject);
                }
            }
            if ("functional-group".equals(formObject.getString("type"))) {
                String value = formObject.getString("value");
                if (Objects.nonNull(value) && value.contains("_")) {
                    String[] group = value.split(",");
                    List<Object> list = new ArrayList<>(group.length);
                    for (int i = 0; i < group.length; i++) {
                        String[] userRadio = group[i].split("_");
                        JSONObject userObject = new JSONObject();
                        userObject.put("label", userRadio[0]);
                        userObject.put("value", userRadio[1]);
                        list.add(userObject);
                    }
                    formObject.put("value", list);
                }
            }
            if ("date".equals(formObject.getString("type"))) {
                String value = DateUtils.timeFormatter(formObject.getString("value"), "d-M-yyyy", "yyyy-MM-dd");
                formObject.put("value", value);
            }
            if ("upload".equals(formObject.getString("type"))) {
                JSONArray jsonArray = resolveUploadValueArray(formObject);
                if (Objects.nonNull(jsonArray)) {
                    List<Map<String, String>> fileList = new ArrayList<>();
                    for (int i = 0; i < jsonArray.size(); i++) {
                        String file = jsonArray.getString(i);
                        if (Objects.nonNull(file) && file.contains(" || ")) {
                            String[] files = file.split(" \\|\\| ");
                            Map<String, String> fileMap = new HashMap<>(2);
                            fileMap.put(files[0], files[1]);
                            fileList.add(fileMap);
                        }
                    }
                    formObject.put("value", fileList);
                }
            }
            transformFields.add(formObject.toJavaObject(Object.class));
        }
        return transformFields;
    }

    private JSONArray resolveUploadValueArray(JSONObject formObject) {
        Object value = formObject.get("value");
        if (value instanceof String) {
            //针对表单未提交，从流程变量中赋值的场景
            JSONArray array = new JSONArray();
            array.add(value);
            return array;
        }
        if (value instanceof JSONArray) {
            return (JSONArray) value;
        }
        logger.info("文件上传控件数据格式错误：{}", value);
        return null;
    }

    public void transformVariables(List<FormField> fields, Map<String, Object> variables) {
        List<String> userList = new ArrayList<>();
        List<String> groupList = new ArrayList<>();
        List<String> uploadList = new ArrayList<>();
        for (FormField field : fields) {
            if ("userRadio".equals(field.getType())) {
                userList.add(field.getId());
            }
            if ("functional-group".equals(field.getType())) {
                groupList.add(field.getId());
            }
            if ("upload".equals(field.getType())) {
                uploadList.add(field.getId());
            }
        }
        if (Objects.nonNull(variables)) {
            for (Map.Entry<String, Object> entry : variables.entrySet()) {
                if (userList.contains(entry.getKey())) {
                    if (Objects.nonNull(entry.getValue()) && !(entry.getValue() instanceof String)) {
                        JSONObject user = JSONObject.parseObject(JsonUtils.toJson(entry.getValue()));
                        String value = user.get("label") + "_" + user.get("value");
                        variables.put(entry.getKey(), value);
                    }
                }
                if (groupList.contains(entry.getKey())) {
                    if (Objects.nonNull(entry.getValue()) && !(entry.getValue() instanceof String)) {
                        JSONArray group = JSONArray.parseArray(JsonUtils.toJson(entry.getValue()));
                        if (Objects.nonNull(group)) {
                            StringBuilder value = new StringBuilder();
                            for (int i = 0; i < group.size(); i++) {
                                if (i == 0) {
                                    value.append(group.getJSONObject(i).get("label")).append("_").append(group.getJSONObject(i).get("value"));
                                    continue;
                                }
                                value.append(",").append(group.getJSONObject(i).get("label")).append("_").append(group.getJSONObject(i).get("value"));
                            }
                            Map<String, String> map = new HashMap<>(2);
                            map.put("id", value.toString());
                            variables.put(entry.getKey(), map);
                        }
                    }
                }
                if (uploadList.contains(entry.getKey())) {
                    if (Objects.nonNull(entry.getValue()) && !(entry.getValue() instanceof String)) {
                        List<Object> fileList = Collections.singletonList(entry.getValue());
                        if (CollectionUtils.isNotEmpty(fileList)) {
                            StringBuilder value = new StringBuilder();
                            List<Map<String, String>> fileMap = (List<Map<String, String>>) fileList.get(0);
                            for (int i = 0; i < fileMap.size(); i++) {
                                for (Map.Entry<String, String> fileEntry : fileMap.get(i).entrySet()) {
                                    if (i == 0) {
                                        value.append(fileEntry.getKey()).append(" || ").append(fileEntry.getValue());
                                        continue;
                                    }
                                    value.append(",").append(fileEntry.getKey()).append(" || ").append(fileEntry.getValue());
                                }
                            }
                            variables.put(entry.getKey(), value.toString());
                        }
                    }
                }
            }
        }
    }
}
